「紙上談兵終覺淺,絕知此事要躬行。經過前四天的觀念剖析與架構設計,今天是時候動手砌下第一塊磚頭了。」
前四天我們確立了「人機共讀」的知識庫哲學,並設計了結合 PARA 方法論、Atomic Notes 與 標準 YAML Frontmatter 的資料結構。今天(Day 05)是我們的實作起手式!我們將從零建立整個專案的專屬 Git Repository——obsidian-agent-brain,並搭建好包含 Go CLI 工具、Obsidian 範例 Vault 與 Claude Code 專屬配置 的完整開發環境。完成今天的步驟後,你將擁有一個隨時可以編譯、測試並讓 AI Agent 登陸運行的實戰骨架。
首先,我們在 Terminal 建立專案資料夾並開啟它。整個 Repo 的目錄結構設計如下:
obsidian-agent-brain/
├── .claude/ # Claude Code Custom Sub-agents & Commands
│ └── commands/ # 存放自訂 Agent 命令 (如 refine-inbox.md)
├── vault/ # 實體 Obsidian Vault (可用 Obsidian 直接開啟)
│ ├── 00_Inbox/ # 待處理草稿暫存區
│ ├── 10_Projects/ # 專案區
│ ├── 20_Areas/ # 長期領域區
│ ├── 30_Resources/ # 靜態資源與手冊
│ └── 40_Archives/ # 歸檔區
├── cmd/
│ └── brain/ # Go 主程式進入點 (brain-cli)
│ └── main.go
├── pkg/ # 核心 Go 套件
│ ├── vault/ # 檔案掃描、Frontmatter 拆分與 AST 解析
│ ├── index/ # 記憶體索引與搜尋引擎
│ └── graphify/ # 轉譯 Graphify JSON 圖譜
├── CLAUDE.md # Claude Code 專屬指引與筆記規範
├── Makefile # 自動化建置與開發指令
├── go.mod
└── go.sum
打開 Terminal,執行以下指令建立 Go Module 並安裝我們後續會用到的核心依賴:
# 1. 建立專案目錄
mkdir obsidian-agent-brain && cd obsidian-agent-brain
# 2: 初始化 Go Module
go mod init obsidian-agent-brain
# 3. 安裝 Markdown AST 解析器 (goldmark) 與 YAML 解析器 (yaml.v3)
go get github.com/yuin/goldmark
go get gopkg.in/yaml.v3
go get github.com/spf13/cobra
三個套件今天先裝起來,但只有一個今天會真的用到:
goldmark:Markdown AST 解析器,Day 08-11 掃描 vault、解析 Wikilink 時會用到,今天先裝不寫呼叫程式碼。yaml.v3:YAML 解析器,之後解析筆記 Frontmatter(Day 04 定義的 id/title/type/status 等欄位)會用到,今天同樣只裝不用。cobra:CLI 框架,今天就會用到——cmd/brain/main.go 直接用它建立可執行的 root command。子指令(capture、scan、health……)會從 Day 07 起陸續疊加,手刻 os.Args 判斷式短期最省事,但遲早要重構成框架;現在就導入 Cobra,讓每天疊加子指令的邊際成本維持穩定。接著,我們建立 vault/ 資料夾,並補齊 PARA 五大目錄結構:
mkdir -p vault/00_Inbox
mkdir -p vault/10_Projects
mkdir -p vault/20_Areas
mkdir -p vault/30_Resources
mkdir -p vault/40_Archives
# 為各目錄補上 .gitkeep 確保空資料夾能被 Git 追蹤
touch vault/00_Inbox/.gitkeep
touch vault/10_Projects/.gitkeep
touch vault/20_Areas/.gitkeep
touch vault/30_Resources/.gitkeep
touch vault/40_Archives/.gitkeep
💡 小撇步:現在你可以打開你的 Obsidian 桌面端,選擇 "Open folder as vault",並直接指向這個 obsidian-agent-brain/vault/ 資料夾。這樣你在 Terminal 的修改就能實時反映在 Obsidian 畫面上!
在專案根目錄下建立 CLAUDE.md。這是 Claude Code Agent 登陸專案時第一個讀取的檔案,我們在這裡定義整個專案的開發指令與筆記處理原則:
# CLAUDE.md
本檔案提供給 Claude Code Agent(或任何在此 repo 內操作的 AI Agent)閱讀,說明專案背景、目錄用途與必須遵守的行為守則。
## 專案簡介
`obsidian-agent-brain` 是 iThome 2026 鐵人賽系列「用 Go + Claude Code Agent + Obsidian(未來搭配 Graphify)打造工程師第二大腦」的 demo repo。核心是 `brain-cli`(`cmd/brain`),目標讓 Agent 能掃描、解析、維護一個以 PARA 方法組織的 Obsidian vault:讀取筆記的 YAML Frontmatter、建立索引、檢查連結健康度,最終匯出給 Graphify 做知識圖譜視覺化。
目前(Day 05)僅完成骨架:可執行的 Cobra root command、一組 PARA 範例 vault、一個 table-driven 占位測試。尚未實作任何掃描或解析邏輯,那是 Day 06 起的範疇。
## 目錄結構說明
obsidian-agent-brain/
├── go.mod / go.sum # Go 模組定義
├── Makefile # init/tidy/build/run/test/fmt/vet/check/clean 指令
├── vault_test.go # 占位測試
├── cmd/brain/main.go # CLI 進入點,Cobra root command,尚無子指令邏輯
├── internal/ # 未來核心邏輯(掃描、Frontmatter 解析、索引)的落腳處,Go 編譯器強制不可被外部模組 import
└── vault/ # PARA 範例 Obsidian vault(暫定範例,正式 vault-structure 規範待 Day 02 change 校正)
├── 00_Inbox/ # 零阻力暫存區
├── 10_Projects/ # 有截止日期的短期任務
├── 20_Areas/ # 長期維護的技術領域
├── 30_Resources/ # 靜態參考資料與工具手冊
└── 40_Archives/ # 已完成專案與過期資料
- 每篇 `vault/` 下的筆記都必須符合 `note-metadata-schema` 規範(必填 `id`/`title`/`date`/`type`/`status` 五個 Frontmatter 欄位,規範詳見規劃 repo 的 `openspec/specs/note-metadata-schema/spec.md`)。
- `cmd/`、`internal/` 的分工與 CLI 框架選型理由記錄在 [`docs/design.md`](docs/design.md)。
## 行為守則
1. **不可竄改筆記 Frontmatter 必填欄位**:`id`、`title`、`date`、`type`、`status` 五個欄位一旦寫入,不可未經確認就修改或刪除;`title` 必須與檔名(去除 `.md`)完全一致。若操作目的就是要修正這些欄位,需先向使用者確認意圖,不可自行判斷「順手修正」。
2. **異動筆記前先確認檔案路徑存在**:在對 `vault/` 下任何筆記進行讀取、修改、搬移或刪除之前,先確認該路徑確實存在,避免對不存在的檔案操作或誤建立重複檔案;跨資料夾搬移筆記時,同樣先確認目的路徑的資料夾已存在。
這兩條是本階段最小的行為守則,更完整的整理規範與 slash command 邏輯(例如 `/refine-inbox`、`/new-adr`)留待 Day 14 的 CLAUDE.md 提示詞工程階段補齊。
工程師的開發體驗(DX)非常重要。我們寫一個輕量的 Makefile,讓未來的編譯與測試命令一鍵完成:
.PHONY: help init tidy build run test fmt vet check clean
BINARY := brain
CMD := ./cmd/brain
help: ## 顯示可用指令
@grep -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | awk 'BEGIN {FS = ":.*?## "}; {printf " \033[36m%-10s\033[0m %s\n", $$1, $$2}'
init: ## 下載依賴(初次 clone 後執行)
go mod download
tidy: ## 整理 go.mod/go.sum(新增或移除 import 後手動執行;會清掉尚未被引用的預裝套件,非上線前必要步驟不要隨意跑)
go mod tidy
build: ## 編譯 brain CLI 至 bin/
go build -o bin/$(BINARY) $(CMD)
run: ## 執行 brain CLI(額外參數用 ARGS="...")
go run $(CMD) $(ARGS)
test: ## 執行所有測試
go test ./...
fmt: ## 檢查程式碼格式(gofmt)
gofmt -l .
vet: ## 執行靜態檢查(go vet)
go vet ./...
check: fmt vet test ## 一次執行 fmt + vet + test
clean: ## 移除建置產物
rm -rf bin/
package main
import (
"fmt"
"os"
"github.com/spf13/cobra"
)
func main() {
rootCmd := &cobra.Command{
Use: "brain",
Short: "obsidian-agent-brain 的核心 CLI",
}
if err := rootCmd.Execute(); err != nil {
fmt.Fprintln(os.Stderr, err)
os.Exit(1)
}
}
這裡刻意不掛任何子指令、也不解析 os.Args——今天的目標只是驗證「Cobra root command 可以執行、可以回應 --help」這條通路。capture、scan、health 這些子指令留給 Day 07 起以 rootCmd.AddCommand(...) 逐一掛上去。
make build # go build -o bin/brain ./cmd/brain
make run ARGS="--help"
make check # fmt + vet + test 一次執行
make test 會跑一個占位測試,驗證 vault/ 五個資料夾都存在,斷言採用 testify(assert)而不是手刻 if err != nil { t.Errorf(...) },以 table-driven 風格逐一檢查:
func TestVaultParaFoldersExist(t *testing.T) {
tests := []struct{ name, folder string }{
{"Inbox", "vault/00_Inbox"},
{"Projects", "vault/10_Projects"},
// ...
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
info, err := os.Stat(tt.folder)
assert.NoError(t, err)
assert.True(t, info.IsDir())
})
}
}
最後一項驗證,是確認 Claude Code 能不能正確讀到今天寫的 CLAUDE.md:在 obsidian-agent-brain/ 目錄下啟動 claude,隨口問「這個專案的行為守則是什麼」,若能正確複述出 Frontmatter 保護規則與路徑確認規則,就代表設定被正確讀取。
至此,我們的 obsidian-agent-brain Demo Repo 與開發環境已經全數就位!我們擁有了乾淨的 Go 專案目錄、PARA 架構的本地 Obsidian Vault,以及載入了規則的 Claude Code 指揮中心。地基已經打穩,接下來就是注入核心力量的時刻!
👉 明天 Day 06,我們將正式進入 Go 語言實作:「brain-cli 登場:用 Go 打造高效率 Vault 處理器」。我們將開始撰寫 internal/vault 套件,實作對 Obsidian 檔案的高速遍歷與基礎資訊抽取!我們明天見!